package com.example.picturestorage.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.picturestorage.bean.Book;
import com.example.picturestorage.bean.Publisher;
import com.example.picturestorage.exception.BookNotFoundException;
import com.example.picturestorage.service.BookService;
import com.example.picturestorage.service.PublisherService;
import com.github.pagehelper.PageInfo;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 28116
 */
@Controller
public class BookController {

    private final static Logger LOGGER = LoggerFactory.getLogger(BookController.class);

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private BookService bookService;

    @Autowired
    private PublisherService publisherService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ExecutorService executorService;


    @PostMapping("/book")
    public String addBook(HttpServletRequest request, @RequestParam("file") MultipartFile multipartFile) throws IOException, ParseException {
        String fileName =/* UUID.randomUUID()+ */multipartFile.getOriginalFilename();
        if (StringUtils.isBlank(fileName)) {
            return "文件名不能为空";
        }
        if (!multipartFile.isEmpty()) {
            byte[] bytes = multipartFile.getBytes();
            BufferedOutputStream bufferedOutputStream = new
                    BufferedOutputStream(new FileOutputStream(new File("src/main/resources/static/imgs/" + fileName)));
            bufferedOutputStream.write(bytes);
            bufferedOutputStream.close();
        }
        LOGGER.info(request.getParameter("bookName"));
        Book book = new Book();
        book.setBookName(request.getParameter("bookName"));
        book.setPath("/static/imgs/" + fileName);
        book.setPublishDate(new Date(new SimpleDateFormat("yyyy-MM-dd").parse(request.getParameter("publishDate")).getTime()));
        book.setAmount(Integer.parseInt(request.getParameter("amount")));
        book.setPrice(new BigDecimal(request.getParameter("price")));
        String publisherName = request.getParameter("publisherName");
        Publisher publisher = publisherService.findPublisherByName(publisherName);
        if (publisher != null) {
            book.setPublisher(publisher);
        } else {
            publisherService.addPublisher(new Publisher(0, publisherName,null,null));
            Publisher publisher1 = publisherService.findPublisherByName(publisherName);
            book.setPublisher(publisher1);
        }
        LOGGER.info("出版日期: " + book.getPublishDate());
        int i = bookService.addBook(book);
        LOGGER.info("generatedKey: " + book.getId());
        return "addBook";
    }

    @PostMapping("/books")
    @ResponseBody
    public PageInfo<Book> findAllBook(@RequestParam(value = "page", defaultValue = "1") int page,
                                      @RequestParam(value = "pageSize", defaultValue = "6") int pageSize,
                                      HttpServletRequest request, Model model) {
//        modelAndView.addObject(allBook);
        LOGGER.info(String.valueOf(pageSize));
        LOGGER.info(request.getParameter("pageSize"));
        PageInfo<Book> bookFenYe = bookService.findBookFenYe(page, pageSize);
        LOGGER.info(String.valueOf(bookFenYe));
        model.addAttribute("bookFenye", bookFenYe);
        return bookFenYe;
    }

    @GetMapping("/books")
//    @ResponseBody
    public String findAllBook2(@RequestParam(value = "page", defaultValue = "1") int page,
                               @RequestParam(value = "pageSize", defaultValue = "6") int pageSize,
                               @org.jetbrains.annotations.NotNull HttpServletRequest request, @NotNull Model model) {
//        modelAndView.addObject(allBook);
        LOGGER.info(String.valueOf(pageSize));
        LOGGER.info(request.getParameter("pageSize"));
        PageInfo<Book> bookFenYe = bookService.findBookFenYe(page, pageSize);
        LOGGER.info(String.valueOf(bookFenYe));
        model.addAttribute("bookFenye2", bookFenYe);
        BookController bookController = new BookController();
        LOGGER.info("bookController " + bookController);
        LOGGER.info("bookService " + bookService);
        return "allBook";
    }


    @Transactional(rollbackFor = {Exception.class})
    @RequestMapping("/deleteAllBook")
    public String deleteAllBook() {
        bookService.deleteAllBook();
        return "addBook";
    }


    @GetMapping("/book/{id}")
    public String bookDetail2(Model model, HttpStatus httpStatus, @PathVariable Integer id) {
        int bookId = id;
        Book book1 = new Book();
        book1.setId(bookId);
        Book book = bookService.findBookById(book1);
//        book.setPrice(new BigDecimal("100"));
        if (book != null) {
            LOGGER.info(String.valueOf(book));
            model.addAttribute("book", book);
        } else {
            throw new BookNotFoundException("没有该书籍!");
        }
        return "bookDetail";
    }

    @GetMapping("/restBook/{id}")
    @ResponseBody
    public String restBook(@PathVariable("id") Integer id, HttpServletRequest httpServletRequest) {
        String name = httpServletRequest.getParameter("name");
        ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost/book/" + id, String.class, name);
        return entity.toString() + " " + name;
    }

    @RequestMapping("/redisSet")
    public String redisSet() {
        Book book1 = new Book();
        book1.setId(13);
        Book book = bookService.findBookById(book1);
        String s = JSON.toJSONString(book);
        redisTemplate.opsForValue().set("book" + book.getId(), s);

        redisTemplate.opsForHash().put("book.hash.13", "id", book.getId() + "");
        HashMap<String, String> map = new HashMap<>();
        map.put("bookName", book.getBookName());
        map.put("amount", book.getAmount() + "");
        redisTemplate.opsForHash().putAll("book.hash.13", map);
        return "allBook";
    }

    @RequestMapping("/redisGet")
    public String redisGet() throws ParseException {
        LOGGER.info("redisGet: " + redisTemplate.opsForValue().get("book" + 13));
        String s = redisTemplate.opsForValue().get("book" + 13);
        String bookName = (String) redisTemplate.opsForHash().get("book.hash.13", "bookName");
        LOGGER.info("bookNameByHash: " + bookName);
        JSONObject jsonBook = JSONObject.parseObject(s);
        LOGGER.info(String.valueOf(jsonBook));
        Book book = new Book();
        book.setPrice(new BigDecimal(jsonBook.getString("price")));
        book.setAmount(Integer.parseInt(jsonBook.getString("amount")));
        book.setPublishDate(new Date(new SimpleDateFormat("yyyy-MM-dd").parse(jsonBook.getString("publishDate")).getTime()));
        book.setPath(jsonBook.getString("path"));
        book.setBookName(jsonBook.getString("bookName"));
        book.setId(Integer.parseInt(jsonBook.getString("id")));
        LOGGER.info(String.valueOf(book));
        return "allBook";
    }

    @DeleteMapping("/book/{id}")
    public String deleteBookById(@PathVariable("id") Integer id) {
        bookService.deleteBookById(id);
        return "allBook";
    }

    @RequestMapping("/jsonTest")
    @ResponseBody
    public String jsonTest() {
        for (int i = 0; i < 11; i++) {
            executorService.execute(() -> {
                Book book = new Book();
                book.setBookName("测试");
                bookService.addBook(book);
                LOGGER.info(Thread.currentThread().getName() + " " + book);
            });
        }
        executorService.shutdown();
        bookService.deleteBookOverId(22);
        return "[{name:\"Tom\",\"age\":19,a:[[{a:1,b:[{a:a},{b:a}]}],[[{b:2}],[{c:3}]]]},{name:\"Tom2\"}]";
    }

    @RequestMapping("/aTest")
    @ResponseBody
    public Book aTest(@RequestBody Book book) {
        return new Book();
    }

    /**
     * 重定向和请求转发测试,注意结果加斜杠/,请求转发和重定向是把请求发给controller而不是html页面
     *
     * @return String
     */
    @RequestMapping("/first")
    public String show() {
        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("name", "BNTang");

        return "redirect:/second";
//        return "forward:/second";
    }

    @RequestMapping("/second")
    public String forwarding() {
        return "first2";
    }

    public static class Main {
        public static void main(String[] args) {
            HashSet<Integer> hashSet = new HashSet<>(4);
            hashSet.add(1);
            hashSet.add(2);
            hashSet.add(3);
            hashSet.add(4);
        }
    }

    @GetMapping("/bookWithPublisher/{id}")
    @ResponseBody
    public Book findBookWithPublisherByBookId(@PathVariable("id") Integer bookId) {
        return bookService.findBookWithPublisherByBookId(bookId);
    }

    public static class Main1 {

        static ReentrantLock lock = new ReentrantLock();

        public static void main(String[] args) {
            ReentrantLock reentrantLock = new ReentrantLock();
            try {
                reentrantLock.lock();
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                reentrantLock.unlock();
            }

            new Thread(Main1::f1).start();
//            new Thread(Main1::f1).start();
        }

        public static void f1() {
            lock.lock();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            JSON json = new JSONArray();
            json.writeJSONString(new StringBuilder("[{'asd':'a'}]"));
            JSONArray objects = new JSONArray();
            objects.writeJSONString(new StringBuilder("[{'asd':'a'}]"));
            System.out.println("json.toJSONString() = " + json.toJSONString());
            System.out.println("objects = " + objects);
            JSONArray objects1 = new JSONArray();
            objects1.add(1);
            objects1.add(2);
            System.out.println("objects1.toJSONString() = " + objects1.toJSONString());

        }
    }

    public static class Main12 {
        public static void main(String[] args) {
            String fileName = "D:\\";
            File topFile = new File(fileName);
            System.out.println("topFile.isDirectory() = " + topFile.isDirectory());
            if (!topFile.isDirectory() && !topFile.exists()) {
                return;
            }
//            while (true) {
            if (topFile.isDirectory()) {
                for (File listFile : topFile.listFiles()) {
                    System.out.println(!listFile.isDirectory() ? "文件: " + listFile.getAbsoluteFile().getPath() + "\n" : "目录: " + listFile.getAbsoluteFile().getPath() + "\n");
                }
            }
//            }
            System.out.println("sum(5) = " + sum(5));

        }

        public static int sum(int n) {
            if (n == 1) {
                return 1;
            }
            return sum(n - 1) * n;
        }
    }
}
